import os
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from datetime import datetime, timedelta
import matplotlib.dates as mdates

# 设置字体以支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题


class ShowCarFlowSpeed:
    def __init__(self, flow_path, speed_path):
        self.flow_path = flow_path
        self.speed_path = speed_path
        self.data = {}
        self.data_zao = {}
        self.p85 = None
        self.slope = None   # 斜率
        self.intercept = None   # 截距

    def show(self):
        print(self.data)
        # 提取数据
        # speed = [d['speed'] for d in self.data.values() if 'speed' in d]
        # flow = [d['flow'] for d in self.data.values() if 'flow' in d]
        # data = {
        #     'x': flow,
        #     'y': speed
        # }
        # fig, ax = plt.subplots()
        # plt.scatter(data['x'], data['y'], color='blue', label='Data Points')  # 绘制散点图

        keys = list(self.data.keys())
        # 将时间字符串转换为datetime对象
        times = [datetime.strptime(time, '%H:%M') for time in keys]
        y_data = [d['y'] for d in self.data.values() if 'y' in d]

        plt.plot(times, y_data, marker='o', linestyle='-', color='r', label='平均速度')

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        # ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式

        # 添加标签和标题
        ax.set_xlabel('时间')
        ax.set_ylabel('差值百分比（%）')
        ax.set_title('小客车全天时间-速度统计')

        # 显示图表
        plt.show()

    def show_zao(self):
        print(self.data_zao)
        # 提取数据
        speed = [d['speed'] for d in self.data_zao.values() if 'speed' in d]
        flow = [d['flow'] for d in self.data_zao.values() if 'flow' in d]
        data = {
            'x': np.array(flow),
            'y': np.array(speed)
        }

        # 计算y值的均值和标准差
        mean_y = np.mean(data['y'])
        std_dev_y = np.std(data['y'])
        # 定义一个阈值，比如两倍的标准差
        threshold = 1.0 * std_dev_y
        # 筛选出不在均值加减两倍标准差之外的点
        filtered_indices = np.where(np.abs(data['y'] - mean_y) < threshold)[0]
        # print(mean_y, std_dev_y, threshold, type(filtered_indices))
        x_filtered = data['x'][filtered_indices]
        y_filtered = data['y'][filtered_indices]
        # 线性拟合
        coefficients = np.polyfit(x_filtered, y_filtered, 1)

        # # 线性拟合
        # coefficients = np.polyfit(data['x'], data['y'], 1)  # 第三个参数1表示一阶多项式，即线性方程
        # coefficients返回的是从高次到低次的系数
        self.slope = coefficients[0]  # 斜率
        self.intercept = coefficients[1]  # 截距
        # 打印结果
        print(f"拟合得到的线性方程为: y = {self.slope:.2f} * x + {self.intercept:.2f}")
        # 创建一个连续的x轴用于绘制拟合直线
        x_line = np.linspace(min(data['x']), max(data['x']), 100)
        y_line = self.slope * x_line + self.intercept

        fig, ax = plt.subplots()
        # 绘制拟合直线
        plt.plot(x_line, y_line, color='red', label='Fitted line')
        plt.scatter(data['x'], data['y'], color='blue', label='Data Points')  # 绘制散点图
        # 添加标签和标题
        ax.set_xlabel('流量（辆）')
        ax.set_ylabel('平均速度（米/秒）')
        ax.set_title('小客车全天流量-速度统计')

        # 显示图表
        plt.show()

    def get_data_zao(self):
        df_flow = pd.read_csv(self.flow_path)
        data0 = df_flow.to_dict(orient='records')
        data_flow = {}
        for i in range(len(data0)):
            data_flow[data0[i]['time']] = data0[i]
        df_speed = pd.read_csv(self.speed_path)
        data1 = df_speed.to_dict(orient='records')
        data_speed = {}
        for i in range(len(data1)):
            data_speed[data1[i]['transtime_up']] = data1[i]
        # 遍历所有的时间点（确保涵盖两个字典中的所有时间）
        all_times = set(data_speed.keys())
        for time in sorted(all_times):
            flow = data_flow.get(time)
            speed = data_speed.get(time)
            self.data_zao[time] = {
                'flow': speed['count'] if speed is not None else 0,  # 如果没有up_flow数据，默认为0
                'speed': speed['mean_speed'] if speed is not None else 0  # 如果没有down_flow数据，默认为0
            }

    def get_data(self):
        df_speed = pd.read_csv(self.speed_path)
        data1 = df_speed.to_dict(orient='records')
        data_speed = {}
        for i in range(len(data1)):
            data_speed[data1[i]['transtime_up']] = data1[i]
        # 遍历所有的时间点（确保涵盖两个字典中的所有时间）
        all_times = set(data_speed.keys())
        meraged = {}
        for time in sorted(all_times):
            flow = data_speed.get(time)
            speed = data_speed.get(time)
            time = time.split(' ')[1][:5]
            meraged[time] = {
                'flow': flow['count'] if flow is not None else 0,  # 如果没有up_flow数据，默认为0
                'speed': speed['mean_speed'] if speed is not None else 0  # 如果没有down_flow数据，默认为0
            }
        for time, data in meraged.items():
            y = data['flow'] * self.slope + self.intercept
            self.data[time] = {
                'y': abs(data['speed'] - y) / y * 100
            }


if __name__ == '__main__':
    # A区中度1
    # path = r'D:\GJ\项目\事故检测\output\G004251002000620010,G004251001000320010-20240131\car_slow_move_data.csv'
    # A区重度1
    # path = r'D:\GJ\项目\事故检测\output\G004251002000620010,G004251001000320010-20240207\car_slow_move_data.csv'
    # A区重度2
    # path = r'D:\GJ\项目\事故检测\output\G004251002000620010,G004251001000320010-20240219\car_slow_move_data.csv'
    # A区重度3
    # path = r'D:\GJ\项目\事故检测\output\G004251001000310010,G004251002000610010-20240205\car_slow_move_data.csv'
    # A区轻度1
    # path = r'D:\GJ\项目\事故检测\output\G004251001000310010,G004251002000610010-20240117\car_slow_move_data.csv'
    # path = r'D:\GJ\项目\事故检测\output\G004251001000310010,G004251002000610010-20240330\car_slow_move_data.csv'

    # B区
    # path = r'D:\GJ\项目\事故检测\output\G004251001000210010,G004251001000310010-20240421\car_slow_move_data.csv'
    # path = r'D:\GJ\项目\事故检测\output\G004251001000320010,G004251001000220010-20240502\car_slow_move_data.csv'
    # 其他
    # path = r'D:\GJ\项目\事故检测\output\G004251001000210010,G004251001000310010-20240101\car_slow_move_data.csv'

    # C区
    # path = r'D:\GJ\项目\事故检测\output\G004251001000120020,G004251001000120010-20240416\car_slow_move_data.csv'

    name = "G004251002000620010,G004251001000320010-20240404"
    path0 = r'D:\GJ\项目\事故检测\output\邻垫高速'
    path1 = os.path.join(path0, name, 'mate_flow_data.csv')
    path2 = os.path.join(path0, name, 'car_time_data.csv')

    # y = -0.02 * x + 26.10

    showCarFlowSpeed = ShowCarFlowSpeed(path1, path2)

    # 拟合流量-平均速度线性方程
    showCarFlowSpeed.get_data_zao()
    showCarFlowSpeed.show_zao()
    # 与线性方程的误差百分比
    showCarFlowSpeed.get_data()
    showCarFlowSpeed.show()

